home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
mail
/
mailleds.93
/
mailleds
/
mailleds-0.93
/
mailleds.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-14
|
9KB
|
473 lines
/*
* mailleds - Check for new mail, blinking keyboard leds when it arrives
* Copyright (C) 1996 Benjamin Osheroff
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*
* Author: Benjamin Osheroff (mtr@ratbert.bagel.org)
* 106 Meernaa Ave.
* Fairfax, CA 94930
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <getopt.h>
#include <signal.h>
#include <time.h>
#include <paths.h>
#include <pwd.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/kd.h>
#include <utmp.h>
#ifdef X_SUPPORT
#include <X11/X.h>
#include <X11/Xlib.h>
#endif
#include "config.h"
#include "mailleds.h"
sig_atomic_t exit_now = 0;
char opt_a, opt_h, opt_q, opt_l, opt_t, opt_u, opt_x, *opt_m, *opt_d;
char *pid_filename;
char *username;
int kbd_leds = 0x0;
int port_leds = 0x0;
/* array of open file descriptors of ttys whose leds must be flashed */
int ct[MAX_CONSOLES];
/* X Display whose leds must be flashed */
#ifdef X_SUPPORT
Display *dpy;
#endif
/* array of X leds that are to be flashed */
int x_leds[3];
int uid, euid, pid;
void usage(void)
{
fprintf(stderr, "usage: mailleds [ -afhkqtx ] [ -m filename ] [ -l [cns] ] [ -d dpy ]\n");
fprintf(stderr, "Options:\n");
fprintf(stderr, "-a, --answering-machine : blink number of messages on led\n");
fprintf(stderr, "-h, --help : brings up this help screen\n");
fprintf(stderr, "-k, --kill : kills a running mailleds daemon\n");
fprintf(stderr, "-q, --quiet : die quietly if another mailleds process exists\n");
fprintf(stderr, "-t, --ttys : specifies that mailleds should flash the vt's leds.\n");
fprintf(stderr, " (This is the default if -d is not specified but keyboard LEDs are.)\n");
fprintf(stderr, "--version : displays version number\n");
fprintf(stderr, "-u, --user <user> : runs mailleds as if you were <user>. You must be root to specify this.\n");
fprintf(stderr, "-l, --leds [cnsp<number>]\n");
fprintf(stderr, " : c, n, and s are keyboard LEDs mailleds will blink.\n");
#ifdef PARALLEL_SUPPORT
fprintf(stderr, " : p<number> corresponds to LEDs hooked up to a port.\n");
#endif
#ifdef X_SUPPORT
fprintf(stderr, "-x : flash the leds on a X display.\n");
fprintf(stderr, "-d, --display dpy : tells mailleds which X display to use.");
fprintf(stderr, " Optional, defaults to current display.\n");
#endif
fprintf(stderr, "-m, --mailbox filename : use 'filename' as a mailbox file\n");
}
static struct option long_options[] =
{
{"message-count", 0, 0, 'a'},
{"leds", 1, 0, 'l'},
{"help", 0, 0, 'h'},
{"display", 0, 0, 'd'},
{"kill", 0, 0, 'k'},
{"quiet", 0, 0, 'q'},
{"version", 0, 0, 'v'},
{"mailbox", 1, 0, 'm'},
{"ttys", 0, 0, 't'},
{"user", 1, 0, 'u'},
{0, 0, 0, 0}
};
void parse_argv(argc, argv)
int argc;
char *argv[];
{
int other_process_pid;
int index = 0;
char opt;
char *program;
struct passwd *pass_info;
kbd_leds = 0x00;
port_leds = 0x00;
/* first, parse the name given. */
program = rindex(*argv, '/');
if (program == NULL) {
program = *argv;
} else
program++;
if (strcmp(program, "xmailleds") == 0)
opt_x = 1;
while (1) {
opt = getopt_long(argc, argv, "ahkqxtl:m:d:u:", long_options, &index);
if (opt == -1)
break;
switch (opt) {
case 'a':
opt_a = 1;
break;
case 'h':
usage();
exit(0); /* printing help was succesful */
break;
case 'k':
set_pidfilename();
other_process_pid = get_pid_from_file(pid_filename);
if (other_process_pid) {
if (kill(other_process_pid, SIGTERM)) {
perror("mailleds");
exit(-2);
}
fprintf(stderr, "mailleds: process %d killed sucessfully\n", other_process_pid);
exit(0);
} else {
fprintf(stderr, "mailleds: no process running for %s\n", username);
exit(1);
}
break;
case 'q':
opt_q = 1;
break;
case 'v':
fprintf(stderr, "mailleds version %s\n", VERSION);
exit(0);
break;
case 'm':
opt_m = strdup(optarg);
break;
case 't':
opt_t = 1;
break;
case 'x':
opt_x = 1;
break;
case 'u':
if (uid != 0) {
fprintf(stderr, "mailleds: only root can specify -u\n");
exit(-1);
}
/* here we effectively become the user in -u */
free(username);
username = strdup(optarg);
pass_info = getpwnam(username);
uid = pass_info->pw_uid;
opt_u = 1;
break;
case 'd':
opt_d = strdup(optarg);
opt_x = 1;
break;
case 'l':
while (*optarg && *optarg != ' ') {
switch (*optarg) {
case 'n':
kbd_leds |= LED_NUM;
break;
case 'c':
kbd_leds |= LED_CAP;
break;
case 's':
kbd_leds |= LED_SCR;
break;
#ifdef PARALLEL_SUPPORT
case 'p':
switch (*++optarg) {
case '1':
port_leds |= PORT_LED_1;
break;
case '2':
port_leds |= PORT_LED_2;
break;
case '3':
port_leds |= PORT_LED_3;
break;
case '4':
port_leds |= PORT_LED_4;
break;
case '5':
port_leds |= PORT_LED_5;
break;
case '6':
port_leds |= PORT_LED_6;
break;
case '7':
port_leds |= PORT_LED_7;
break;
case '8':
port_leds |= PORT_LED_8;
break;
default:
fprintf(stderr, "mailleds: no such led p%c", *optarg);
exit(-1);
}
break;
#endif /* PARALLEL_SUPPORT */
default:
fprintf(stderr, "mailleds: Unknown LED '%c'\n", *optarg);
exit(-1);
}
optarg++;
}
break;
case '?':
usage();
exit(-1);
break;
case ':':
usage();
exit(-1);
break;
}
}
/* default behavior */
if (!opt_t && !opt_x && !port_leds)
opt_t = 1;
if (!opt_m)
opt_m = get_mailfile();
if (!kbd_leds && (opt_x || opt_t))
kbd_leds = DEF_KBD_LEDS;
if (kbd_leds && !opt_x && !opt_t)
opt_t = 1;
if (!kbd_leds && !port_leds) {
kbd_leds = DEF_KBD_LEDS;
port_leds = DEF_PORT_LEDS;
}
#ifdef X_SUPPORT
if (opt_x)
get_X_leds_from_kbd_leds(kbd_leds);
#endif
}
void fatal_error_signal(int sig)
{
exit_now = 1;
}
void exit_cleanly()
{
setreuid(uid, euid);
unlink(pid_filename);
exit(0);
}
void exit_fatal(const char *reason)
{
setreuid(uid, euid);
unlink(pid_filename);
fprintf(stderr, "mailleds: %s\n", reason);
exit(1);
}
void set_up_signals()
{
signal(SIGINT, fatal_error_signal);
signal(SIGTERM, fatal_error_signal);
}
time_t
get_time_of(filename)
char *filename;
{
static struct stat i;
if (stat(filename, &i))
return (rand()); /* If unable to stat, this forces the mailfile check / wait functions to kick in. */
return (i.st_ctime);
}
void stat_error(filename)
char *filename;
{
char *msg;
msg = (char *) xmalloc(strlen("mailleds: ") + strlen(filename) + 1);
sprintf(msg, "mailleds: %s", filename);
perror(msg);
exit_fatal("File access error");
}
int main(argc, argv)
int argc;
char *argv[];
{
FILE *mailbox;
time_t newmod;
struct passwd *uinfo;
int mail = 0;
time_t lastmod = 0;
uid = getuid();
euid = geteuid();
if (!opt_u) {
uinfo = getpwuid(uid);
username = strdup(uinfo->pw_name);
}
/* don't need to know pid to know pid filename */
parse_argv(argc, argv);
set_pidfilename();
if (!opt_x)
pid_check();
#ifndef DEBUG
switch (fork()) {
case -1: /* Cannot fork */
perror("fork");
exit(1);
case 0: /* Son process */
break;
default: /* Father process */
exit(0);
}
#endif
if (!opt_x) {
pid = getpid();
write_pidfile();
detach_from_tty();
}
#ifdef PARALLEL_SUPPORT
if (port_leds) {
if ((ioperm(LPT_PORT, 1, 1)) == -1) {
fprintf(stderr, "unable to set permissions on port 0x%x\n",
LPT_PORT);
perror("mailleds");
exit(1);
}
}
#endif
setreuid(euid, uid);
set_up_signals();
while (!exit_now) {
newmod = get_time_of(opt_m);
if (lastmod != newmod) {
mailbox = open_mailbox_file(opt_m);
mail = count_mail(mailbox);
lastmod = newmod;
fclose(mailbox);
}
if (kbd_leds) {
if (opt_t)
make_tty_array();
#ifdef X_SUPPORT
if (opt_x) {
dpy = XOpenDisplay(opt_d);
if (dpy == (Display *) NULL)
exit_fatal("Cannot open Display");
XCloseDisplay(dpy);
}
#endif
if (!port_leds && opt_t && *ct == -1 && !opt_u) /* we never exit with port_leds */
exit_fatal("Couldn't locate your login tty");
}
if (mail) {
if (!opt_x)
setreuid(uid, euid);
if (opt_a) {
blink_x(BLINK_TIME_ON, BLINK_TIME_OFF, mail);
usleep(TIME_BETWEEN_COUNTS);
} else {
blink_once(BLINK_TIME_ON, BLINK_TIME_OFF);
usleep(TIME_BETWEEN_COUNTS);
}
if (!opt_x)
setreuid(euid, uid);
} else {
sleep(INTERVAL_BETWEEN_CHECKS);
}
}
exit_cleanly();
}